package com.zt.bus.order.service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zt.bus.constant.BusConstant;
import com.zt.bus.line.inter.DiscountDetailMapper;
import com.zt.bus.line.model.Discount;
import com.zt.bus.line.model.DiscountDetail;
import com.zt.bus.line.model.Line;
import com.zt.bus.line.model.LinePlan;
import com.zt.bus.line.model.LinePlanDiscount;
import com.zt.bus.line.model.LinePlanRefund;
import com.zt.bus.line.model.Refund;
import com.zt.bus.line.model.RefundDetail;
import com.zt.bus.line.service.DiscountService;
import com.zt.bus.line.service.LinePlanService;
import com.zt.bus.line.service.LineService;
import com.zt.bus.line.service.RefundService;
import com.zt.bus.order.model.Order;
import com.zt.bus.order.model.OrderBack;
import com.zt.bus.order.model.OrderBackInfo;
import com.zt.bus.order.model.OrderBackRefund;
import com.zt.bus.order.model.OrderBackRefund.OrderBackRefundDetail;
import com.zt.bus.order.model.OrderDiscount;
import com.zt.system.model.BusinessException;
import com.zt.system.service.BaseService;
import com.zt.util.DateUtil;
import com.zt.util.LogUtil;
import com.zt.util.StringUtil;

import net.sf.json.JSONObject;

/**
 * 订单金额计算
 */
@Service
public class OrderAmountService extends BaseService {

    @Autowired
    private LineService lineService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderBackService orderBackService;
    @Autowired
    private LinePlanService linePlanService;
    @Autowired
    private DiscountService discountService;
    @Autowired
    private RefundService refundService;
    @Autowired
    private DiscountDetailMapper discountDetailMapper;

    /**
     * 计算订单原始（不打折）价格
     *
     * @param lineId
     * @param planId
     * @param dates
     */
    public double getOrderAmount(String lineId, String planId, List<Date> dates, int passengerCount) {
        if (StringUtil.isEmpty(lineId) || StringUtil.isEmpty(planId) || dates == null || dates.size() == 0 || passengerCount <= 0) {
            throw new BusinessException("订单费用计算，缺少参数！");
        }
        Line line = lineService.getById(lineId);
        if (line == null || BusConstant.LineStatus.DISABLE.equals(line.getLineStatus())) {
            throw new BusinessException("线路不存在！");
        }
        LinePlan linePlan = linePlanService.getById(planId);
        if (linePlan == null  || (!BusConstant.LinePlanStatus.TO_BE_OPEN.equals(linePlan.getPlanStatus())
                && !BusConstant.LinePlanStatus.HAS_BEEN_OPENED.equals(linePlan.getPlanStatus()))) {
            throw new BusinessException("方案不存在！");
        }
        // todo 判断是否发车
        return doubleAround2(line.getPrice() * dates.size() * passengerCount) ;
    }

    /**
     * 获取优惠方案及各方案对应的价格
     *
     * @param lineId
     * @param planId
     * @param dates
     */
    public List<OrderDiscount> getDiscount(String lineId, String planId, List<Date> dates, int passengerCount) {
        if (StringUtil.isEmpty(lineId) || StringUtil.isEmpty(planId) || dates == null || dates.size() == 0 || passengerCount <= 0) {
            throw new BusinessException("订单折扣计算，缺少参数！");
        }
        List<OrderDiscount> list = new ArrayList<>();
        double orderAmount = getOrderAmount(lineId, planId, dates, passengerCount);

        List<LinePlanDiscount> planDiscounts = linePlanService.getLinePlanDiscounts(planId);
        for (LinePlanDiscount planDiscount : planDiscounts) {
            if (!BusConstant.LinePlanDiscountStatus.ENABLE.equals(planDiscount.getStatus())) {
                continue;
            }
            if (DateUtil
                    .compare(DateUtil.formatDate(new Date()), DateUtil.formatDate(planDiscount.getExpirationDate())) > 0) {// 不在有效期内
                continue;
            }
            Discount discount = discountService.getById(planDiscount.getDiscountId());
            if (discount == null) {
                LogUtil.getLogger().error("折扣方案[" + planDiscount.getDiscountId() + "]不存在！");
            }
            if (orderAmount < discount.getAmountGtThan()) {// 订单金额没达到，不能使用
                continue;
            }
            List<DiscountDetail> discountDetails = discount.getDetails();
            if (discountDetails == null || discountDetails.size() == 0) {// 没有方案明细
                continue;
            }
            DiscountDetail matchDetail = null;
            for (DiscountDetail detail : discountDetails) {
                if (BusConstant.DiscountType.DAYS_RATE.equals(discount.getType())) {// 累积天数
                    if (dates.size() >= detail.getDays()) {
                        matchDetail = detail;
                    } else {
                        continue;
                    }
                } else {// 按照开始时间
                    if (!new Date().before(detail.getStartDate()) && !new Date().after(detail.getEndDate())) {
                        matchDetail = detail;
                    } else {
                        continue;
                    }
                }
            }
            if (matchDetail != null) {
                OrderDiscount orderDiscount = new OrderDiscount();
                orderDiscount.setDiscountId(discount.getId());
                orderDiscount.setDiscountName(discount.getName());
                orderDiscount.setDiscountDetailId(matchDetail.getId());
                orderDiscount.setDiscountRate(matchDetail.getDiscountRate());
                BigDecimal b1 = new BigDecimal(Double.toString(orderAmount));
                BigDecimal b2 = new BigDecimal(Double.toString(matchDetail.getDiscountRate()));
                orderDiscount.setDiscountAmount(doubleAround2(b1.multiply(b2).doubleValue()));
                list.add(orderDiscount);
            }
        }
        return list;
    }

    public static double doubleAround2(double d) {
        // 如果不需要四舍五入，可以使用RoundingMode.DOWN

        return new BigDecimal(new Double(d).toString()).doubleValue();
    }

    /**
     * 获得获取可退金额 可退金额 = 退款金额-手续费
     *
     * @param orderId
     * @param list
     * @return
     */
    public JSONObject getCanRefundAmount(String orderId, List<OrderBackInfo> list) {
        JSONObject result = new JSONObject();
        List<OrderBackRefund> orderBackRefunds = getOrderBackRefunds(orderId, list);
        double backTotalAmount = 0, backTotalFee = 0;
        int totalDays = 0;// 所有乘客退订总天数
        for (OrderBackRefund backRefund : orderBackRefunds) {
        	totalDays += backRefund.getDetails().size();
            backTotalFee += backRefund.getBackFee();
        }
        //订单
    	Order order = orderService.getById(orderId);
        backTotalAmount = getRefundAmount(totalDays, order, BusConstant.OrderBackType.BACK_USER);// 用户主动退款
        if(backTotalAmount>0){
    		// 退款方案
    		Refund refund = refundService.getRefundByPlanId(order.getPlanId());
    		// 最低手续费
    		backTotalFee = backTotalFee >= refund.getMinimumFee() ? backTotalFee : refund.getMinimumFee();
        }else {// 没钱可退
        	backTotalFee = 0;
        	backTotalAmount = 0;
        }
        BigDecimal b1 = new BigDecimal(Double.toString(backTotalAmount));
        BigDecimal b2 = new BigDecimal(Double.toString(backTotalFee));
        DecimalFormat df = new DecimalFormat("######0.00");
        double price = doubleAround2(b1.subtract(b2).doubleValue());
        if(price <= 0){
        	price = 0.0;
        }
        result.put("price", df.format(price));
        return result;
    }

	/**
	 * 获得全部乘客订单退款金额
	 *
	 * @param days
	 *            累计退订天数
	 * @param order
	 *            订单
	 * @param orderBackType
	 *            退订订单类型
	 * @return
	 */
	public double getRefundAmount(int days, Order order, String orderBackType) {
		double discountedAmount = order.getDiscountedAmount();// 折扣后金额(用户支付金额)
		int orderDays = order.getDays(); // 原天数

		// 如果有退款记录 还需把已退的金额减掉
		double refundedAmount = 0;// 订单已退金额
		int refundedDays = 0;// 订单已退天数
		List<OrderBack> refundedOrder = orderBackService.getRefundedOrder(order.getId());// 退款成功的订单
		for (OrderBack orderBack : refundedOrder) {
			refundedAmount += orderBack.getRefundAmount();
			refundedDays += orderBack.getDays();
		}
		discountedAmount = discountedAmount - refundedAmount;// 订单原始金额 - 订单已退金额
		orderDays = orderDays - refundedDays;// 订单原始天数 - 订单已退天数

		Double totlePrice = 0.0;

		int back_days = orderDays - days; // 累计退款后剩余的天数
		if (back_days < 0) {
			throw new BusinessException("扣款计算错误!");
		}

		// 退款后剩余的订单天数不参与任何的折扣方案,按订单原价进行计算(后期考虑重新计算折扣)
		double remainder_amount = order.getPrice() * back_days; // 退款后剩余天数的金额

		if (BusConstant.OrderBackType.BACK_ADMIN.equals(orderBackType)) {// 管理员后台手动退订
			List<OrderBack> orderBackList = orderBackService.getOrderBackListByUser(order.getId());
			if (orderBackList != null && orderBackList.size() > 0) {// 用户主动退过款
			} else {
				DiscountDetail discountDetail = discountDetailMapper.selectByPrimaryKey(order.getDiscountDetailId());
				if (discountDetail != null) {
					remainder_amount = remainder_amount * discountDetail.getDiscountRate();// 用户没有退过款的情况下管理员退款仍享受原先折扣
				}
			}
		}
		// 管理员退订 剩余订单任享受折扣
		if (discountedAmount >= remainder_amount) {
			totlePrice = discountedAmount - remainder_amount; // 得到需要退款的金额
		}
		return Double.parseDouble(new DecimalFormat("#.##").format(totlePrice));
	}

    /**
     * 获取订单退款方案明细，根据发车时间计算，某个乘客如果退订，将不再享受折扣
     *
     * @param orderId
     * @param orderBackInfos
     *            用户退订日期
     * @return
     */
    public List<OrderBackRefund> getOrderBackRefunds(String orderId, List<OrderBackInfo> orderBackInfos) {
        Long applyTime = new Date().getTime();// 申请退款时间
        List<OrderBackRefund> orderBackRefundList = new ArrayList<>();
        Order order = orderService.getById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在！");
        }
        LinePlanRefund linePlanRefund = linePlanService.getLinePlanRefund(order.getPlanId());
        if (linePlanRefund == null) {
            throw new BusinessException("订单退款方案不存在！");
        }
        
		Refund refund = refundService.getById(linePlanRefund.getRefundId());
		for (OrderBackInfo orderBackInfo : orderBackInfos) {
			OrderBackRefund orderBackRefund = new OrderBackRefund();
			List<String> dateList = orderBackInfo.getDates();
			orderBackRefund.setPhone(orderBackInfo.getPassengerPhone());
			orderBackRefund.setName(orderBackInfo.getPassengerName());

            List<OrderBackRefundDetail> details = new ArrayList<>();
            for (String date : dateList) {

                OrderBackRefundDetail orderBackRefundDetail = orderBackRefund.new OrderBackRefundDetail();// 退款方案明细

                orderBackRefundDetail.setDate(date);
                orderBackRefundDetail.setRefundId(refund.getId());
                orderBackRefundDetail.setRefundName(refund.getName());

                RefundDetail refundDetail = new RefundDetail();
                // 根据退款方案类型进行区分
                if(BusConstant.RefundType.FIXED_COSTS.equals(refund.getType())){// 固定费用
                	if(refund.getDetails().size() > 1){
                		throw new BusinessException("退款方案配置错误!");
                	}
                	refundDetail = refund.getDetails().get(0);// 固定费用的退款方案只有一天退款方案明细
                	orderBackRefundDetail.setRefundDetailId(refundDetail.getId());
                    orderBackRefundDetail.setRefundFee(refundDetail.getFixedFee());// 固定手续费
                }else {// 发车前时间折扣率
                	  // 每天订单发车时间
                    Long time = DateUtil.parseDateTime(date + " " + this.getFormatDepartureTime(order.getDepartTime()))
                            .getTime();
                    // 拿用户申请退款时间去和发车时间做比较
                    int minutes = Integer.parseInt(String.valueOf((time - applyTime) / 1000 / 60));// 距离发车的时间(分钟)
                    
                    for (int j = 0; j < refund.getDetails().size(); j++) {
                        if (minutes <= refund.getDetails().get(j).getMinutes() && j == 0) {
                            refundDetail = refund.getDetails().get(j);
                            break;
                        }
                        if (minutes > refund.getDetails().get(j).getMinutes() && j == refund.getDetails().size() - 1) {
                            refundDetail = refund.getDetails().get(j);
                            break;
                        }
                        if (minutes > refund.getDetails().get(j).getMinutes()
                                && minutes <= refund.getDetails().get(j + 1).getMinutes()) {
                            refundDetail = refund.getDetails().get(j + 1);
                            break;
                        }
                    }
                    orderBackRefundDetail.setRefundDetailId(refundDetail.getId());
                    orderBackRefundDetail.setRefundRate(refundDetail.getRefundRate());
                    orderBackRefundDetail.setRefundFee(order.getPrice()* orderBackRefundDetail.getRefundRate());// 通过线路单价进行计算
                }
          
                details.add(orderBackRefundDetail);
            }
            orderBackRefund.setDetails(details);
            orderBackRefundList.add(orderBackRefund);
        }
        return orderBackRefundList;
    }

    /**
     * 获取格式化后的上车时间
     *
     * @param departureTime
     * @return
     */
    public String getFormatDepartureTime(String departureTime) {
        if (StringUtil.isNotEmpty(departureTime)) {
            if (Integer.parseInt(departureTime.split(":")[0]) < 12) {
                return "0" + departureTime + ":00";
            } else {
                return departureTime + ":00";
            }
        } else {
            return "00:00:00";
        }

    }
}
